home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * serial.c: Serial port access functions.
- * Part of MP, the MIDI Playground.
- *
- * Author: Daniel Barrett
- * Version: See the file "version.h".
- * Copyright: None! This program is in the Public Domain.
- * Please share it with others.
- ***************************************************************************/
-
-
- #include "mp.h"
- #include "midi.h"
-
- static struct MsgPort *MidiPort = NULL;
- static struct IOExtSer *Midi = NULL;
- long serialFlags = 0L;
-
- #define F_MIDIPORT 1
- #define F_MIDI 2
- #define F_DEVICE 4
- #define F_SERPARAMS 8
-
-
- BOOL AllDigits(char *str);
- char *GetEnv(char *str);
- BOOL MakeSerialDeviceName(char *str, char *device, int *unit);
-
-
- /****************************************************************************
- * SerialSetup: Open the serial port and its message port.
- * Allow for an alternate MIDI device in an environment variable.
- ***************************************************************************/
-
- BOOL SerialSetup(FLAGS sysex)
- {
- char deviceName[BUFSIZ], *envVar;
- int unit;
-
- /* Set the defaults. */
-
- strcpy(deviceName, DEFAULT_MIDI_DEVICE);
- unit = DEFAULT_MIDI_UNIT;
-
- /* If environment variable is set, find the real MIDI device info. */
-
- if ((envVar = GetEnv(MIDI_ENV_VAR))
- && (!MakeSerialDeviceName(envVar, deviceName, &unit)))
- return(FALSE);
-
- /* Create a port. */
-
- if (! (MidiPort = CreatePort(0, 0)) )
- {
- fprintf(stderr, "Cannot create port\n");
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_MIDIPORT;
-
- /* Create an extended I/O structure. */
-
- if (! (Midi = (struct IOExtSer *)
- CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
- {
- fprintf(stderr, "Cannot create extended I/O structure\n");
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_MIDI;
-
- /* Open the serial device. */
-
- Midi->io_SerFlags = SERF_SHARED;
- if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
- {
- fprintf(stderr,
- "Cannot open serial device \"%s\", unit %d.\n",
- deviceName, unit);
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_DEVICE;
-
- /* Set the serial device parameters. */
-
- Midi->io_SerFlags = SERF_RAD_BOOGIE;
- if (sysex)
- {
- Midi->io_TermArray.TermArray0 = 0xF7F7F7F7;
- Midi->io_TermArray.TermArray1 = 0xF7F7F7F7;
- Midi->io_SerFlags |= SERF_EOFMODE;
- }
- Midi->io_Baud = MIDI_BAUD_RATE;
- Midi->io_ExtFlags = 0; /* For future compatibility */
- Midi->IOSer.io_Command = SDCMD_SETPARAMS;
-
- if (DoIO((struct IORequest *)Midi) != 0)
- {
- fprintf(stderr, "Cannot set serial parameters.\n");
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_SERPARAMS;
-
- return(TRUE);
- }
-
-
- /****************************************************************************
- * SerialShutdown: Close the serial port and its message port.
- ***************************************************************************/
-
- void SerialShutdown(void)
- {
- if (serialFlags & F_DEVICE)
- {
- ResetSerialPort();
- AbortIO((struct IORequest *)Midi);
- WaitIO((struct IORequest *)Midi);
- CloseDevice((struct IORequest *)Midi);
- }
-
- if (serialFlags & F_MIDI)
- DeleteExtIO((struct IORequest *)Midi);
-
- if (serialFlags & F_MIDIPORT)
- DeletePort(MidiPort);
- }
-
- /****************************************************************************
- * ResetSerialPort: Clear all data from the serial port.
- ***************************************************************************/
-
- void ResetSerialPort(void)
- {
- Midi->IOSer.io_Command = CMD_CLEAR;
- DoIO((struct IORequest *)Midi);
- }
-
-
- /****************************************************************************
- * Is any data there?
- ***************************************************************************/
-
- long AnyMidiData(void)
- {
- Midi->IOSer.io_Command = SDCMD_QUERY;
- DoIO((struct IORequest *)Midi);
- return(Midi->IOSer.io_Actual);
- }
-
-
- /****************************************************************************
- * PrepareToReadMidi: Prepare a READ request for the MIDI port.
- * PrepareToWriteMidi: Prepare a WRITE request for the MIDI port.
- ***************************************************************************/
-
- void PrepareToReadMidi(UBYTE buf[], int len)
- {
- Midi->IOSer.io_Command = CMD_READ;
- Midi->IOSer.io_Data = (APTR)buf;
- Midi->IOSer.io_Length = len;
- }
-
-
- void PrepareToWriteMidi(UBYTE buf[], int len)
- {
- Midi->IOSer.io_Command = CMD_WRITE;
- Midi->IOSer.io_Data = (APTR)buf;
- Midi->IOSer.io_Length = len;
- }
-
-
- /****************************************************************************
- * DoTheIO: General-purpose MIDI I/O routine. Quits on ^C.
- ****************************************************************************/
-
- long DoTheIO(void)
- {
- int mask, temp;
- long bytesDone = 0L;
-
- mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
- SendIO((struct IORequest *)Midi);
-
- while (1)
- {
- temp = Wait(mask);
- if (temp & SIGBREAKF_CTRL_C)
- {
- bytesDone = CTRL_C_NO_BYTES;
- break;
- }
-
- if (CheckIO((struct IORequest *)Midi))
- {
- WaitIO((struct IORequest *)Midi);
- bytesDone = Midi->IOSer.io_Actual;
- break;
- }
- }
-
- AbortIO((struct IORequest *)Midi);
- WaitIO((struct IORequest *)Midi);
- return(bytesDone);
- }
-
-
- /****************************************************************************
- * Fast serial reading routine, from idea on 1.3 RKM's page 863.
- * If any data is waiting, get all of it with DoIO(). Otherwise, post an
- * asynchronous request for 1 byte. Repeat this in the calling program.
- ****************************************************************************/
-
- long FastSerialRead(UBYTE buf[])
- {
- long bytesWaiting, bytesRead;
-
- if ((bytesWaiting = AnyMidiData()) > 0)
- {
- PrepareToReadMidi(buf, MIN(bytesWaiting, BUFSIZ));
- DoIO((struct IORequest *)Midi);
- return(Midi->IOSer.io_Actual);
- }
- else
- {
- PrepareToReadMidi(buf, 1);
- return(DoTheIO());
- }
- }
-
-
- /****************************************************************************
- * Allow the use of another MIDI device than serial.device.
- * Environment variable syntax is "DEVICENAME:UNITNUMBER".
- * For example: "midi.device:2".
- *
- * "device" MUST be preallocated.
- ****************************************************************************/
-
- BOOL MakeSerialDeviceName(char *str, char *device, int *unit)
- {
- while (str && *str && (*str != ':'))
- *(device++) = *(str++);
-
- *device = '\0';
-
- if ((*str != ':') || *(str+1) == '\0')
- {
- fprintf(stderr,
- "Your MIDI device name (variable "
- MIDI_ENV_VAR
- ") is missing a colon\nand/or a unit number.\n");
- return(FALSE);
- }
- str++;
-
- if (!AllDigits(str))
- {
- fprintf(stderr,
- "Your MIDI device unit number (variable "
- MIDI_ENV_VAR
- ") must be\na positive integer.\n");
- return(FALSE);
- }
- else
- *unit = atoi(str);
-
- return(TRUE);
- }
-
-
- /* AllDigits: Return TRUE iff the string "str" consists only of digits. */
-
- BOOL AllDigits(char *str)
- {
- if ((!str) || (*str == '\0')) /* NULL or empty string. */
- return(FALSE);
- else
- while (*str) /* For each character... */
- if (!isdigit(*str)) /* if not a digit... */
- return(FALSE); /* goodbye! */
- else
- str++;
- return(TRUE); /* All were digits. */
- }
-